package uk.co.q3c.deplan.server.util.rules;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Id;

import uk.co.q3c.deplan.client.domain.AbstractDomainObject;
import uk.co.q3c.deplan.client.domain.DomainKind;
import uk.co.q3c.deplan.client.domain.DomainObject;
import uk.co.q3c.deplan.client.domain.resource.PersistenceReferenceException;
import uk.co.q3c.deplan.server.util.useraccess.UserAccessController;
import uk.co.q3c.deplan.server.util.validation.rules.ObjectRule;
import uk.co.q3c.deplan.server.util.validation.rules.PropertyRule;
import uk.co.q3c.deplan.server.util.validation.rules.PropertyValuer;
import uk.co.q3c.deplan.server.util.validation.rules.ValidationObjectRule;

import com.googlecode.objectify.Key;

/**
 * @see UserAccessController
 * @see PropertyFormatter
 * @see WidgetFormatter
 * @see LayoutController
 * @see Validator
 * @author DSowerby 12 May 2009
 * 
 * @param <P>
 * @param <O>
 */
public class RuleManager<P extends PropertyRule, O extends ObjectRule> extends AbstractDomainObject implements Serializable {

	private static final long serialVersionUID = 1L;
	private Map<String, List<P>> propertyRules;
	private ArrayList<O> objectRules;
	private final PropertyValuer parent;
	@Id
	private Long keyId;

	public RuleManager(PropertyValuer parent) {
		super();
		this.parent = parent;
	}

	@SuppressWarnings("unused")
	private RuleManager() {
		super();
		parent = null;
	}

	@Override
	protected void beforeLoad() {
		super.beforeLoad();
		if (propertyRules == null) {
			propertyRules = new HashMap<String, List<P>>();
		}
		if (objectRules == null) {
			objectRules = new ArrayList<O>();
		}
	}

	public void addPropertyRules(String propertyName, List<P> ruleSet) {

		propertyRules.put(propertyName, ruleSet);
	}

	public void removePropertyRules(String propertyName) {

		propertyRules.remove(propertyName);
	}

	public void addObjectRule(O rule) {

		objectRules.add(rule);
	}

	public void removeObjectRule(ValidationObjectRule rule) {

		objectRules.remove(rule);
	}

	public List<P> propertyRules(String propertyName) {

		return propertyRules.get(propertyName);
	}

	public void addPropertyRule(String propertyName, P rule) {

		List<P> list = propertyRules.get(propertyName);
		if (list == null) {
			list = new ArrayList<P>();
			propertyRules.put(propertyName, list);
		}
		list.add(rule);

	}

	public PropertyValuer getParent() {

		return parent;
	}

	public ArrayList<O> objectRules() {

		return objectRules;
	}

	@Override
	public DomainKind getKind() {
		return DomainKind.General;
	}

	public Long getKeyId() {
		return keyId;
	}

	@Override
	public Key<? extends DomainObject> getKey() throws PersistenceReferenceException {
		throw new RuntimeException("Not yet implemented");
	}

	@Override
	public void setKeyId(Long keyId) {
		throw new RuntimeException("Not yet implemented");
	}
}
